﻿/*
   Author: Tomer Paz
   games.com
   2007
*/

// game board implementation. it is a Fields container (part of the fields), hence
// it implements IContainer too and uses iterator for the fields, But unlike other containers
// it creates All fields at once rather than providing inteface for "pushing" fields one by one.
// builder class

package monopoly.GameBoard {

	import flash.events.*;
	import flash.display.Loader;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;
	import monopoly.IFS.iterators.IIterator;
	import monopoly.IFS.iterators.ArrayIterator;
	import monopoly.IFS.Collections.ICollection;
	import monopoly.Field.Field;
	import monopoly.DBA.IDBClient;
	import monopoly.DBA.DBClient;
	import monopoly.IFS.GLOBALS;
	
	// a game board Data. there can be few instances of game board, on each are few fields. 
	// game board Data responsible to define data fields and arrange them on it's surface
	// unlike usual Data model classes, the GameBoard is Not dispatching events since it's data is Predefined and constant 
	// once it's initialized
	
	public class GameBoard extends EventDispatcher implements ICollection
		{
		private var _NumOfFields:uint;
		private var _FieldGroups:Dictionary = new Dictionary( );
		private var _LoadedImageCounter:uint;
		//private var _BoardSize:uint;
		private var _BoardWidth:Number;
		private var _BoardHeight:Number;
		private var _Fields:Array;
		private var _BitmapsArr:Array;	// shall contain references to all URL-loaded Field Property loaders which contain images (bitmap Data)
		private var _WebServerRootURL:String;
		private var _StartPoint:uint;
		//TPAZ - add background image:
		private var _Background:URLRequest;
		
		public function GameBoard(NumOfFields:uint, BoardWidth:Number, BoardHeight:Number, WebServerRootURL:String, StartPoint:uint):void
			{
			_NumOfFields = NumOfFields;
			_LoadedImageCounter = 0;	// init
			// to be used by "Viewers"...
			_BoardWidth = BoardWidth;
			_BoardHeight = BoardHeight;
			//_BoardSize   = BoardSize;
			
			_WebServerRootURL = WebServerRootURL;
			_StartPoint  = StartPoint;
			
			/* TP 09/09 - add board background image, taken from DB */
			
			var dbClient:IDBClient = DBClient.getInstance(null, null);
//			var loader:Loader = new Loader();
			var url:String = new String(_WebServerRootURL);
			url = url.concat("/", dbClient.game_data[0].board_image);
			
//			var urlReq:URLRequest = new URLRequest(url);
//			loader.load(urlReq);
//			_Background = loader;
			_Background = new URLRequest(url);
			}

		/* load set of fields property images from Web server, then when done - create fields */

		public function loadPropertyImages():void
			{
			_BitmapsArr = new Array();
			var dbClient:IDBClient = DBClient.getInstance(null, null);
			
			/* load #Fields images from Web server */
			var i:int = 0;
			var j:int = 0;
			for ( i = _StartPoint, j = 0; j < _NumOfFields; i++, j++)
				{
				// add fault tolerance:
				if (null == dbClient.properties_list[i])
					break;
				var loader:Loader = new Loader();
				var url:String = new String(_WebServerRootURL);
				url = url.concat("/", dbClient.properties_list[i].image_path);

				//loader.cacheAsBitmap = false;

				configureListeners(loader.contentLoaderInfo);
	
				var urlReq:URLRequest = new URLRequest(url);
				loader.load(urlReq);
				
				/* push Loader instance (!) into container */
				
				_BitmapsArr.push(loader);
				
				/* dispatch notification for gameboard viewer */
		//try to do it inside loader Progress or COMPLETE Event	handler	
//				dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
				}
			}
			
		private function configureListeners(dispatcher:IEventDispatcher):void 
			{
            dispatcher.addEventListener(Event.COMPLETE, completeHandler);
            dispatcher.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
            dispatcher.addEventListener(Event.INIT, initHandler);
            dispatcher.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            dispatcher.addEventListener(Event.OPEN, openHandler);
            dispatcher.addEventListener(ProgressEvent.PROGRESS, progressHandler);
            dispatcher.addEventListener(Event.UNLOAD, unLoadHandler);
	        }
		/* except for ubLKoaderHandler */
		private function removeListeners(dispatcher:IEventDispatcher):void 
			{
            dispatcher.removeEventListener(Event.COMPLETE, completeHandler);
            dispatcher.removeEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
            dispatcher.removeEventListener(Event.INIT, initHandler);
            dispatcher.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
            dispatcher.removeEventListener(Event.OPEN, openHandler);
            dispatcher.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
            dispatcher.removeEventListener(Event.UNLOAD, unLoadHandler);
	        }
			
		private function completeHandler(event:Event):void 
			{
			_LoadedImageCounter += 1;
			
            //trace("completeHandler: " + event);
			
			/* dispatch notification for gameboard viewer for Progress Bar update */
				
			dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
			
			/* no longer need the listners, except for unload */
			
			removeListeners(event.currentTarget as IEventDispatcher);
			
			/* send CHANGE event to Viewers once All Properties have been loaded */
			
			if (_LoadedImageCounter == _NumOfFields)
				{
				CreateFields();
				/* remove progress bar */
				dispatchEvent(new Event(Event.COMPLETE));
				/* tell board view to redraw */
				dispatchEvent(new Event(Event.CHANGE));
				}
			}

        private function httpStatusHandler(event:HTTPStatusEvent):void {
           // trace("httpStatusHandler: " + event);
        }

        private function initHandler(event:Event):void {
           // trace("initHandler: " + event);
        }

        private function ioErrorHandler(event:IOErrorEvent):void {
           // trace("ioErrorHandler: " + event);
        }

        private function openHandler(event:Event):void {
           // trace("openHandler: " + event);
		   
        }

        private function progressHandler(event:ProgressEvent):void {
            // trace("progressHandler: bytesLoaded=" + event.bytesLoaded + " bytesTotal=" + event.bytesTotal);
        }

        private function unLoadHandler(event:Event):void {
           // trace("unLoadHandler: " + event);
        }

		
		/* create the fields */
		
		private function CreateFields():void
			{
			_Fields = new Array(_NumOfFields);
			var dbClient:IDBClient = DBClient.getInstance(null, null);
			
			/* create the fields instances */
			
			for (var i:uint = 0; i < _NumOfFields; i++)
				{
				if (GLOBALS.DEBUG & GLOBALS.DEBUG_LOGIC)
					trace("[GameBoard][CreateFields] DB PropertyID=" + dbClient.properties_list[i]["itm_id"]);
				_Fields[i] = new Field(i, dbClient.properties_list[i]["itm_id"], _BitmapsArr[i]);
				_Fields[i].PropertyName = dbClient.properties_list[i]["name"];
				_Fields[i].PropertyType = dbClient.properties_list[i]["itm_type"];
				_Fields[i].set_XY(dbClient.properties_list[i]["itm_x"], dbClient.properties_list[i]["itm_y"]);
				_Fields[i].Cost 		= dbClient.properties_list[i]["cost"];
				_Fields[i].Group		= dbClient.properties_list[i]["group_id"];
				_Fields[i].MortgageCost	= dbClient.properties_list[i]["mortgage_cost"];
				if (GLOBALS.DEBUG & GLOBALS.DEBUG_LOGIC)
					trace("[GameBoard][CreateFields] Field Position= " + i + ", PropertyID=" + _Fields[i].PropertyID + ", Name=" + _Fields[i].PropertyName);
				
				_FieldGroups[_Fields[i].Group] = _Fields[i].Group;
				}
			}
		
		/* interfaces */
		
		public function get BoardWidth():Number
			{
			return(_BoardWidth);
			}
		public function get BoardHeight():Number
			{
			return(_BoardHeight);
			}
			
		public function get NumOfFields():Number
			{
			return(_NumOfFields);
			}
		public function getFieldsByGroup(group:int):Array
			{
			var fields:Array = new Array( );
			
			for (var i:int = 0; i < _Fields.length; i++)
				{
				if (group == _Fields[i].Group)
					fields.push(_Fields[i]);
				}
			return fields;
			}
		public function get FieldGroups():Dictionary
			{
			return _FieldGroups;
			}
			
		// returns a Reference to bitmaps Loader array	- trying to avoid that currently
		//public function get BitmapsArr():Array { return _BitmapsArr; }
		
		public function GetBitmapAt(index:uint):Loader
			{
			return _BitmapsArr[index];
			}
		public function SetBitmapAt(index:uint, bitmapL:Loader):void
			{
			_BitmapsArr[index] = bitmapL;
			_Fields[index].setActiveProperty(index, bitmapL);	// this operation is triggering a CHANGE update event
			}
		public function GetBackground():URLRequest
			{
			return _Background;
			}
		
		public function iterator(type:String = null):IIterator 
			{
			if (type == "Bitmaps")
				return new ArrayIterator(_BitmapsArr);
			else
				return new ArrayIterator(_Fields);
			}
		}
}